<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Animate a line</title>
    <meta
      name="viewport"
      content="initial-scale=1,maximum-scale=1,user-scalable=no"
    />
    <script src="../../lib/mapbox-gl.js"></script>
    <link href="../../lib/mapbox-gl.css" rel="stylesheet" />
    <script src="../../lib/axios.min.js"></script>
    <style>
      body {
        margin: 0;
        padding: 0;
      }
      #map {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
      }
      #pause {
        position: absolute;
        margin: 20px;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <button id="pause">pause</button>
    <script>
      let baseDataUrl = `http://${localStorage.getItem(
        "host"
      )}/mapbox-gl-js-offline-examples`;
      axios
        .get(
          baseDataUrl +
            `/resources/styles/${localStorage.getItem(
              "mbtilesStylesName"
            )}.json`
        )
        .then((res) => {
          let data = res.data;
          initMap(data);
        })
        .catch((err) => {
          console.error(err);
        });
      function initMap(style) {
        let map = new mapboxgl.Map({
          container: "map",
          center: [103.463, 33.415],
          zoom: 0.5,
          style: style,
        });

        // Create a GeoJSON source with an empty lineString.
        var geojson = {
          type: "FeatureCollection",
          features: [
            {
              type: "Feature",
              geometry: {
                type: "LineString",
                coordinates: [[0, 0]],
              },
            },
          ],
        };

        var speedFactor = 30; // number of frames per longitude degree
        var animation; // to store and cancel the animation
        var startTime = 0;
        var progress = 0; // progress = timestamp - startTime
        var resetTime = false; // indicator of whether time reset is needed for the animation
        var pauseButton = document.getElementById("pause");

        map.on("load", function () {
          // add the line which will be modified in the animation
          map.addLayer({
            id: "line-animation",
            type: "line",
            source: {
              type: "geojson",
              data: geojson,
            },
            layout: {
              "line-cap": "round",
              "line-join": "round",
            },
            paint: {
              "line-color": "#ed6498",
              "line-width": 5,
              "line-opacity": 0.8,
            },
          });

          startTime = performance.now();

          animateLine();

          // click the button to pause or play
          pauseButton.addEventListener("click", function () {
            pauseButton.classList.toggle("pause");
            if (pauseButton.classList.contains("pause")) {
              cancelAnimationFrame(animation);
            } else {
              resetTime = true;
              animateLine();
            }
          });

          // reset startTime and progress once the tab loses or gains focus
          // requestAnimationFrame also pauses on hidden tabs by default
          document.addEventListener("visibilitychange", function () {
            resetTime = true;
          });

          // animated in a circle as a sine wave along the map.
          function animateLine(timestamp) {
            if (resetTime) {
              // resume previous progress
              startTime = performance.now() - progress;
              resetTime = false;
            } else {
              progress = timestamp - startTime;
            }

            // restart if it finishes a loop
            if (progress > speedFactor * 360) {
              startTime = timestamp;
              geojson.features[0].geometry.coordinates = [];
            } else {
              var x = progress / speedFactor;
              // draw a sine wave with some math.
              var y = Math.sin((x * Math.PI) / 90) * 40;
              // append new coordinates to the lineString
              geojson.features[0].geometry.coordinates.push([x, y]);
              // then update the map
              map.getSource("line-animation").setData(geojson);
            }
            // Request the next frame of the animation.
            animation = requestAnimationFrame(animateLine);
          }
        });
      }
    </script>
  </body>
</html>
